package com.jxpanda.starter.config.security.token;


import com.fasterxml.jackson.annotation.JsonIgnore;
import com.jxpanda.commons.toolkit.IdentifierKit;
import com.jxpanda.starter.config.security.AuthenticationProperties;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author Panda
 */
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Token implements UserDetails {

    /**
     * token的ID
     */
    private String id;

    /**
     * 用户名
     */
    private String name;

    /**
     * 密码
     */
    @JsonIgnore
    private String password;

    /**
     * 权限列表
     */
    private List<Authority> authorities;

    /**
     * 过期时间
     */
    private LocalDateTime expireTime;

    /**
     * token是否有效的标识，id有效且没有过期的token视为有效
     */
    @Builder.Default
    private boolean effective = false;

    /**
     * 附加属性，这个Map结构会在token被解析的时候，打散，然后注入到控制器里
     * 要透传的属性放在这里面
     */
    @Builder.Default
    private Map<String, Object> extra = new HashMap<>(8);

    /**
     * token的签名
     */
    @JsonIgnore
    private String signature;

    public boolean isEffective() {
        this.effective = IdentifierKit.isIdEffective(id) && expireTime.isAfter(LocalDateTime.now());
        return this.effective;
    }

    @Override
    @JsonIgnore
    public String getUsername() {
        return name;
    }

    @Override
    @JsonIgnore
    public boolean isAccountNonExpired() {
        return isEffective();
    }

    @Override
    @JsonIgnore
    public boolean isAccountNonLocked() {
        return isEffective();
    }

    @Override
    @JsonIgnore
    public boolean isCredentialsNonExpired() {
        return isEffective();
    }

    @Override
    @JsonIgnore
    public boolean isEnabled() {
        return isEffective();
    }

    public static Token empty() {
        return new Token();
    }

}
